<?php namespace sacvoyage\domain;



require_once('sacvoyage/domain/Resource.php');
require_once('sacvoyage/proxy/Resource.php');


require_once('sacvoyage/http/util.php');
require_once('sacvoyage/util.php');

require_once('sacvoyage/Object.php');
use \sacvoyage\Object;





class Synchronizer {
	
	// syncronize two resources according to config
	public function __construct(/* Resource */ $local, 
	                            /* Resource */ $remote, 
	                            \sacvoyage\Object $config=null) {
	    $this->_local=$local;
	    $this->_remote=$remote;
		$this->_config=$config;
	}
	
	public function synchronize() {
		if($this->_config && isset($this->_config->collections)) {
			$collections=$this->_config->collections;		
		} else {
			if($this->_config && isset($this->_config->mode)) {
				$mode=$this->_config->mode;
			} else {
				$mode='sync';
			}
			$names=array_unique(array_merge(
				$this->_local->getCollectionNames(),
				$this->_remote->getCollectionNames()
			));
			$collections=array();
			foreach($names as $name) {
				// all sys-collections are not syncronized by default
				if($name!='sys' && !starts_with($name, 'sys.')) {
					$collections[$name]=$mode;
				}
			}
		}
		
		echo "<h1>Synchronizing<h1/>\n";
		foreach($collections as $collection=>$mode) {
			echo "<h2>Synchronizing collection $collection<h2/>\n";
			$this->_syncCollections(
				$this->_local->getCollection($collection), 
				$this->_remote->getCollection($collection), 
				$mode
			);
			
		}
	}

	private $_local;
	private $_remote;
	private $_config;
	
	private function _syncCollections($local, $remote, $mode) {
		
		$query=new Object(array(
			'select'=>new Object(array(
				'_id'=>true,
				'_rev'=>true
			)),
			'status'=>'all'
		));
		
		$localKeys=iterator_to_array($local->find($query));
		$remoteKeys=iterator_to_array($remote->find($query));
		
		if($mode=='sync' || $mode=='push') {
			$diff=array_of_objects_diff($localKeys, $remoteKeys);
			$this->_copy($local, $remote, $diff);
			foreach($diff as $doc) {
				echo "<p>".$doc->_id.'~'.$doc->_rev.'</p>';
			}
		}
		
		if($mode=='sync' || $mode=='pull') {
			$diff=array_of_objects_diff($remoteKeys, $localKeys);
			$this->_copy($remote, $local, $diff);
			foreach($diff as $doc) {
				echo "<p>".$doc->_id.'~'.$doc->_rev.'</p>';
			}
		}
	}
	
	/*
	 * copy specified by $keys documents from $source to $destination collection
	 */
	private function _copy($source, $destination, $keys) {
		$query=new Object(array(
			'status'=>'all',
			'filter'=>new Object(array('_or'=>	$keys))
		));
		
		$documents=$source->find($query);
		$written=$destination->write($documents);
	}
	
}

?>
